﻿using System;
using System.Configuration;
using System.IO;
using System.Text;
using System.Security.Cryptography.X509Certificates;
using System.Security.Cryptography;
using SZJT.Framework.Adapter;

namespace SZJT.Framework
{
    public static class CertService
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="cert"></param>
        /// <returns></returns>
        public static string GetPublicKey(X509Certificate2 cert)
        {
            if (cert == null)
            {
                LoggerHelper.WriteCodePointInfo("传入证书为空");
                return string.Empty;
            }
            return cert.PublicKey.Key.ToXmlString(false);
        }
        /// <summary>
        /// 从本机计算机中查找证书
        /// </summary>
        /// <returns></returns>
        public static X509Certificate2 FindCert(string certName,string storeName,string storeLocation,string certType)
        {        
            var _storeLocal= storeLocation.ToLower().Equals("currentuser") ? StoreLocation.CurrentUser : StoreLocation.LocalMachine;
            var store = new X509Store(storeName, _storeLocal);
            try
            {
                store.Open(OpenFlags.MaxAllowed);
                foreach (X509Certificate2 x509 in store.Certificates)
                {
                    if (x509.Subject.Contains(certName)&&x509.HasPrivateKey)
                    {
                        return x509;
                    }
                }
            }
            catch  { throw new Exception("查询证书时发生错误"); }
            finally
            {
                store.Close();
            }
            throw new Exception("查询证书时发生错误");
        }

        public static string EncryptByPublicKey(string XmlPublicKey, string cleanString)
        {
            var byteConverter = new UTF8Encoding();
            var dataToEncrypt = byteConverter.GetBytes(cleanString);

            var RSA = new RSACryptoServiceProvider();
            RSA.FromXmlString(XmlPublicKey);

            var encryptData = RSA.Encrypt(dataToEncrypt, false);
            var encryptString = Convert.ToBase64String(encryptData);
            var test = Convert.FromBase64String(encryptString);

            return encryptString;
        }

        public static string DecryptByPrivateKey(string privateKey,string encryptString)
        {
            var encryptedDataArray = Convert.FromBase64String(encryptString);
            var provider = new RSACryptoServiceProvider();
            provider.FromXmlString(privateKey);
            var decrypted = provider.Decrypt(encryptedDataArray, false);
            var result = Encoding.ASCII.GetString(decrypted);
            return result;
        }

        public static string DecryptByPrivateKey(X509Certificate2 cert, string encryptString)
        {
            var decrypt = (RSACryptoServiceProvider)cert.PrivateKey;
            var decryptData = Convert.FromBase64String(encryptString);
            var dataToDecrypt = decrypt.Decrypt(decryptData, false);
            var byteConverter = new UTF8Encoding();
            return byteConverter.GetString(dataToDecrypt);
        }

        public  static X509Certificate2 GetLocalCert()
        {
            var config = new ComponentConfiguration();
            var component = config.GetComponent();
            var cert = config.GetCert(component.CertName);
            return FindCert(cert.FindValue, cert.StoreName, cert.StoreLocation, cert.FindType);
        }

        public static string Encode(string str, string key)
        {
            var keyStr = GetKeyStr(key);
            var provider = new DESCryptoServiceProvider
            {
                Key = Encoding.ASCII.GetBytes(keyStr),
                IV = Encoding.ASCII.GetBytes(keyStr)
            };
            var bytes = Encoding.GetEncoding("UTF-8").GetBytes(str);
            var stream = new MemoryStream();
            var stream2 = new CryptoStream(stream, provider.CreateEncryptor(), CryptoStreamMode.Write);
            stream2.Write(bytes, 0, bytes.Length);
            stream2.FlushFinalBlock();
            var builder = new StringBuilder();
            foreach (var num in stream.ToArray())
            {
                builder.AppendFormat("{0:X2}", num);
            }
            stream.Close();
            return builder.ToString();
        }

        private static string GetKeyStr(string key)
        {
            var length = key.Length;
            var flag = 8 - length;
            var result = key;
            if (length > 8)
                return key.Substring(0, 8);
            while (flag > 0)
            {
                result += "*";
                flag--;
            }
            return result;
        }

        public static bool MatchTime(string encrytedData)
        {
            try
            {
                var seconds = Convert.ToInt32(ConfigurationManager.AppSettings["CertTicketValidSeconds"]);
                var dTime = DateTime.Parse(encrytedData);
                var dTimeNow = DateTime.Now;
                TimeSpan ts = dTimeNow - dTime;
                var deltSecs = ts.TotalSeconds;
                return deltSecs <= checked(seconds);
            }
            catch
            {
                return false;
            }
        }
    }
}
